<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="robots" content="noodp" />
        <title>ejson4cpp使用文档 - L_B__</title><meta name="referrer" content="no-referrer">
<meta name="description" content="ejson4cpp使用文档"><meta property="og:title" content="ejson4cpp使用文档" />
<meta property="og:description" content="ejson4cpp使用文档" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" /><meta property="og:image" content="https://acking-you.github.io/logo.png"/><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2023-01-17T00:00:00+00:00" />
<meta property="article:modified_time" content="2023-01-17T00:00:00+00:00" />

<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="https://acking-you.github.io/logo.png"/>

<meta name="twitter:title" content="ejson4cpp使用文档"/>
<meta name="twitter:description" content="ejson4cpp使用文档"/>
<meta name="application-name" content="FeelIt">
<meta name="apple-mobile-web-app-title" content="FeelIt"><meta name="theme-color" content="#ffffff"><meta name="msapplication-TileColor" content="#da532c"><link rel="canonical" href="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" /><link rel="prev" href="https://acking-you.github.io/posts/clion%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%AE%8C%E5%85%A8%E8%A7%A3%E6%9E%90/" /><link rel="next" href="https://acking-you.github.io/posts/c&#43;&#43;%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5%E5%BF%85%E5%A4%87%E6%B5%8B%E8%AF%95%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E8%A6%86%E7%9B%96%E6%B5%8B%E8%AF%95%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E6%A3%80%E6%B5%8B/" /><link rel="stylesheet" href="/css/page.min.css"><link rel="stylesheet" href="/css/home.min.css"><script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "ejson4cpp使用文档",
        "inLanguage": "zh-CN",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "https:\/\/acking-you.github.io\/posts\/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3\/"
        },"genre": "posts","keywords": "ejson4cpp使用文档","wordcount":  5973 ,
        "url": "https:\/\/acking-you.github.io\/posts\/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3\/","datePublished": "2023-01-17T00:00:00+00:00","dateModified": "2023-01-17T00:00:00+00:00","publisher": {
            "@type": "Organization",
            "name": "作者"},"author": {
                "@type": "Person",
                "name": "作者"
            },"description": "ejson4cpp使用文档"
    }
    </script></head><body data-header-desktop="auto" data-header-mobile="auto"><script>(window.localStorage && localStorage.getItem('theme') ? localStorage.getItem('theme') === 'dark' : ('auto' === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : 'auto' === 'dark')) && document.body.setAttribute('theme', 'dark');</script>

        <div id="mask"></div><div class="wrapper"><header class="desktop" id="header-desktop">
    <div class="header-wrapper">
        <div class="header-title">
            <a href="/" title="L_B__">L_B__</a>
        </div>
        <div class="menu">
            <div class="menu-inner"><a class="menu-item" href="/posts/"> 文章 </a><a class="menu-item" href="/tags/"> 标签 </a><a class="menu-item" href="/categories/"> 分类 </a><span class="menu-item delimiter"></span><span class="menu-item search" id="search-desktop">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-desktop">
                        <a href="#" class="search-button search-toggle" id="search-toggle-desktop" title="搜索">
                            <i class="fas fa-search fa-fw"></i>
                        </a>
                        <a href="#" class="search-button search-clear" id="search-clear-desktop" title="清空">
                            <i class="fas fa-times-circle fa-fw"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-desktop">
                            <i class="fas fa-spinner fa-fw fa-spin"></i>
                        </span>
                    </span><a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                    <i class="fas fa-adjust fa-fw"></i>
                </a>
            </div>
        </div>
    </div>
</header><header class="mobile" id="header-mobile">
    <div class="header-container">
        <div class="header-wrapper">
            <div class="header-title">
                <a href="/" title="L_B__">L_B__</a>
            </div>
            <div class="menu-toggle" id="menu-toggle-mobile">
                <span></span><span></span><span></span>
            </div>
        </div>
        <div class="menu" id="menu-mobile"><div class="search-wrapper">
                    <div class="search mobile" id="search-mobile">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-mobile">
                        <a href="#" class="search-button search-toggle" id="search-toggle-mobile" title="搜索">
                            <i class="fas fa-search fa-fw"></i>
                        </a>
                        <a href="#" class="search-button search-clear" id="search-clear-mobile" title="清空">
                            <i class="fas fa-times-circle fa-fw"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-mobile">
                            <i class="fas fa-spinner fa-fw fa-spin"></i>
                        </span>
                    </div>
                    <a href="#" class="search-cancel" id="search-cancel-mobile">
                        取消
                    </a>
                </div><a class="menu-item" href="/posts/" title="">文章</a><a class="menu-item" href="/tags/" title="">标签</a><a class="menu-item" href="/categories/" title="">分类</a><div class="menu-item"><a href="javascript:void(0);" class="theme-switch" title="切换主题">
                    <i class="fas fa-adjust fa-fw"></i>
                </a>
            </div></div>
    </div>
</header><div class="search-dropdown desktop">
    <div id="search-dropdown-desktop"></div>
</div>
<div class="search-dropdown mobile">
    <div id="search-dropdown-mobile"></div>
</div><main class="main">
                <div class="container"><div class="toc" id="toc-auto">
            <h2 class="toc-title">目录</h2>
            <div class="toc-content" id="toc-content-auto"></div>
        </div><article class="page single" data-toc="disable"><div class="featured-image"><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png"
        data-srcset="https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png, https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png 1.5x, https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png 2x"
        data-sizes="auto"
        alt="https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png"
        title="ejson4cpp使用文档" /></div><div class="single-card" data-image="true"><h2 class="single-title animated flipInX">ejson4cpp使用文档</h2><div class="post-meta">
                <div class="post-meta-line"><span class="post-author"><a href="/" title="Author" rel=" author" class="author"><i class="fas fa-user-circle fa-fw"></i>作者</a></span>&nbsp;<span class="post-category">出版于  <a href="/categories/%E4%B8%AA%E4%BA%BA%E9%A1%B9%E7%9B%AE/"><i class="far fa-folder fa-fw"></i>个人项目</a></span></div>
                <div class="post-meta-line"><span><i class="far fa-calendar-alt fa-fw"></i>&nbsp;<time datetime="2023-01-17">2023-01-17</time></span>&nbsp;<span><i class="fas fa-pencil-alt fa-fw"></i>&nbsp;约 5973 字</span>&nbsp;
                    <span><i class="far fa-clock fa-fw"></i>&nbsp;预计阅读 12 分钟</span>&nbsp;</div>
            </div>
            
            <hr><div class="details toc" id="toc-static"  data-kept="">
                    <div class="details-summary toc-title">
                        <span>目录</span>
                        <span><i class="details-icon fas fa-angle-right"></i></span>
                    </div>
                    <div class="details-content toc-content" id="toc-content-static"><nav id="TableOfContents">
  <ul>
    <li><a href="#快速开始">快速开始</a>
      <ul>
        <li><a href="#要求">要求</a></li>
        <li><a href="#安装与引入">安装与引入</a></li>
        <li><a href="#开始使用">开始使用</a></li>
      </ul>
    </li>
    <li><a href="#常见用法">常见用法</a></li>
    <li><a href="#api介绍">API介绍</a>
      <ul>
        <li><a href="#通过命名风格识别api">通过命名风格识别API</a></li>
        <li><a href="#宏定义">宏定义</a></li>
        <li><a href="#fromjson系列函数">FromJSON系列函数</a></li>
        <li><a href="#tojson系列函数">ToJSON系列函数</a></li>
        <li><a href="#jobject系列函数">JObject系列函数</a></li>
      </ul>
    </li>
    <li><a href="#注意事项">注意事项</a></li>
  </ul>
</nav></div>
                </div><div class="content" id="content"><p>代码仓库：https://github.com/ACking-you/ejson4cpp</p>
<p><code>ejosn4cpp</code> ：意味着这是一个使用上非常 <code>easy</code>，同时性能上也非常 <code>efficiency</code> c++ json解析库。 支持c++11及以上，并且完全的跨平台。</p>
<ul>
<li>
<p>使用 <code>easy</code> 体现在：</p>
<ol>
<li>api简单，你只需要关注两个函数（FromJSON、ToJSON），且支持一键json结构体互转。</li>
<li>引入简单，支持cmake命令一键引入项目并使用。</li>
<li>错误定位简单，无论是解析json还是序列化为json，任何错误的操作都会有详细的报错信息（模拟打印了堆栈信息），让错误定位更简单。</li>
</ol>
</li>
<li>
<p>性能 <code>efficiency</code> 体现在：
本机benchmark(3000行json)结果如图：
<img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f279b07fe22434b9fc6d74d82f8792a~tplv-k3u1fbpfcp-zoom-1.image"
        data-srcset="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f279b07fe22434b9fc6d74d82f8792a~tplv-k3u1fbpfcp-zoom-1.image, https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f279b07fe22434b9fc6d74d82f8792a~tplv-k3u1fbpfcp-zoom-1.image 1.5x, https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f279b07fe22434b9fc6d74d82f8792a~tplv-k3u1fbpfcp-zoom-1.image 2x"
        data-sizes="auto"
        alt="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f279b07fe22434b9fc6d74d82f8792a~tplv-k3u1fbpfcp-zoom-1.image"
        title="benchmark" /></p>
<ol>
<li>反序列化（<strong>Parse</strong>)性能明显领先 <code>nlohmann-json</code> 和 <code>jsoncpp</code>，但只有 <code>rapidjson</code> 的一半性能。</li>
<li>序列化（<strong>Stringify</strong>）性能遥遥领先其他所有json库一个数量级。</li>
<li>查找（<strong>FindMember</strong>）：由于看过 <code>rapidjson</code>  源码，发现其内部每个元素的节点是以数组的形式组织的，并没有用到其他高深的数据结构，故专门对他进行成员查找测试，发现确实是 <code>O(n)</code> 级别的查找性能。</li>
</ol>
<p>benchmark的代码仓库：<a href="https://github.com/ACking-you/bench_json4cpp" target="_blank" rel="noopener noreffer">https://github.com/ACking-you/bench_json4cpp</a></p>
</li>
</ul>
<h2 id="快速开始">快速开始</h2>
<h3 id="要求">要求</h3>
<ul>
<li>C++11及以上，是跨全平台的</li>
</ul>
<h3 id="安装与引入">安装与引入</h3>
<p>推荐用以下两种方式进行引入：</p>
<ul>
<li>
<p>方法一：通过cmake中的 <code>FetchContent</code> 模块引入</p>
<ol>
<li>
<p>在项目的cmake中添加下列代码进行引入，国内如果因为网络问题无法使用可以换这个gitee的镜像源：https://gitee.com/acking-you/ejson4cpp.git</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="nb">include</span><span class="p">(</span><span class="s">FetchContent</span><span class="p">)</span><span class="err">
</span><span class="err">
</span><span class="err"></span><span class="nb">FetchContent_Declare</span><span class="p">(</span>
        <span class="s">ejson4cpp</span>
        <span class="s">GIT_REPOSITORY</span> <span class="s">https://github.com/ACking-you/ejson4cpp.git</span>
        <span class="s">GIT_TAG</span> <span class="s">v1.5.2</span>
        <span class="s">GIT_SHALLOW</span> <span class="s">TRUE</span><span class="p">)</span><span class="err">
</span><span class="err"></span><span class="nb">FetchContent_MakeAvailable</span><span class="p">(</span><span class="s">ejson4cpp</span><span class="p">)</span><span class="err">
</span></code></pre></div></li>
<li>
<p>在需要使用该库的目标中链接 <code>ejson</code> 即可。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">target</span>  <span class="s">ejson</span><span class="p">)</span><span class="err">
</span></code></pre></div></li>
</ol>
</li>
<li>
<p>方法二：手动下载包，然后通过cmake命令引入</p>
<ol>
<li>
<p>通过git命令下载项目源码</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell">git clone https://github.com/ACking-you/ejson4cpp.git
</code></pre></div></li>
<li>
<p>将该项目添加到子项目中：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="nb">add_subdirectory</span><span class="p">(</span><span class="s">ejson4cpp</span><span class="p">)</span><span class="err">
</span></code></pre></div></li>
<li>
<p>在需要使用该库的目标中链接 <code>ejson</code> 即可。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">target</span>  <span class="s">ejson</span><span class="p">)</span><span class="err">
</span></code></pre></div></li>
</ol>
</li>
</ul>
<h3 id="开始使用">开始使用</h3>
<p>这里以解析 json 的配置文件映射到 C++ 结构体为例子来进行讲解。</p>
<p>假设有redis、mysql、日志服务需要通过配置文件来进行配置，我们先写下结构体如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">server</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">port</span><span class="p">{};</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">host</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">log</span>
<span class="p">{</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">level</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">filedir</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">formatter</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">config</span>
<span class="p">{</span>
   <span class="n">log</span>    <span class="n">logger</span><span class="p">;</span>
   <span class="n">server</span> <span class="n">redis</span><span class="p">;</span>
   <span class="n">server</span> <span class="n">mysql</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div><p>一个模拟的json配置文件如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="p">{</span>
<span class="nt">&#34;logger&#34;</span><span class="p">:</span> <span class="p">{</span>
  <span class="nt">&#34;filedir&#34;</span><span class="p">:</span> <span class="s2">&#34;home/project/1&#34;</span><span class="p">,</span>
  <span class="nt">&#34;formatter&#34;</span><span class="p">:</span> <span class="s2">&#34;default&#34;</span><span class="p">,</span>
  <span class="nt">&#34;level&#34;</span><span class="p">:</span> <span class="s2">&#34;debug&#34;</span>
<span class="p">},</span>
<span class="nt">&#34;mysql&#34;</span><span class="p">:</span> <span class="p">{</span>
  <span class="nt">&#34;host&#34;</span><span class="p">:</span> <span class="s2">&#34;192.31.1.1&#34;</span><span class="p">,</span>
  <span class="nt">&#34;port&#34;</span><span class="p">:</span> <span class="mi">1314</span>
<span class="p">},</span>
<span class="nt">&#34;redis&#34;</span><span class="p">:</span> <span class="p">{</span>
  <span class="nt">&#34;host&#34;</span><span class="p">:</span> <span class="s2">&#34;127.0.0.1&#34;</span><span class="p">,</span>
  <span class="nt">&#34;port&#34;</span><span class="p">:</span> <span class="mi">1444</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><p>现在要实现的功能是读取json配置文件的数据将 config 结构体进行初始化，我们可以按照下面的步骤进行：</p>
<p>完整代码请看 <a href="https://github.com/ACking-you/ejson4cpp/blob/master/example/example1.cc" target="_blank" rel="noopener noreffer">example/example1.cc</a></p>
<ol>
<li>
<p>让server、log、config这几个自定义类型支持 json 序列化，添加下列宏定义即可：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="c1">// auto generate log/server/config to_json and from_json
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">log</span><span class="p">,</span> <span class="n">level</span><span class="p">,</span> <span class="n">filedir</span><span class="p">,</span> <span class="n">formatter</span><span class="p">)</span>
<span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">logger</span><span class="p">,</span> <span class="n">redis</span><span class="p">,</span> <span class="n">mysql</span><span class="p">)</span>
</code></pre></div></li>
<li>
<p>定义config变量，调用 <code>FromFile</code> 函数，即可完成需求：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">config</span> <span class="n">s_config</span><span class="p">;</span>
<span class="c1">// init config from config.json
</span><span class="c1"></span><span class="n">Parser</span><span class="o">::</span><span class="n">FromFile</span><span class="p">(</span><span class="n">CONFIG_PATH</span><span class="p">,</span> <span class="n">s_config</span><span class="p">);</span>
</code></pre></div><p>如果需要重新写回文件，则可调用 <code>ToFile</code> 函数：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="c1">// write config to file
</span><span class="c1"></span><span class="n">Parser</span><span class="o">::</span><span class="n">ToFile</span><span class="p">(</span><span class="n">CONFIG_PATH</span><span class="p">,</span> <span class="n">s_config</span><span class="p">);</span>
</code></pre></div><p>如果读取json字符串的数据并初始化对应的变量（反序列化）则可以调用 <code>FromJSON</code> 函数：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="c1">// init config struct from json string
</span><span class="c1"></span><span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="n">s_config</span><span class="p">);</span>
</code></pre></div><p>如果需要将变量转化为json字符串（序列化），则可调用 <code>ToJSON</code> 函数：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">auto</span> <span class="n">json_str</span> <span class="o">=</span> <span class="n">Parser</span><span class="o">::</span><span class="n">ToJSON</span><span class="p">(</span><span class="n">s_config</span><span class="p">);</span>
</code></pre></div></li>
</ol>
<p>好的，经过以上两步，你已经学会了整个库的核心用法，没错，这个库提倡使用直接的函数而不是类来实现对应的功能，这样能减少你的记忆和思考过程。当然如果需要更为细致的使用它，你可以去了解 <code>JObject</code> 类的相关用法，在API介绍里面写的很详细。</p>
<h2 id="常见用法">常见用法</h2>
<p>在进行后端开发的过程中，前端传来的数据很多时候是 <code>json</code> 数据，那么我们现在就使用该库来模拟一个简单的后端业务。</p>
<p>比如一个视频平台的评论区，首先映入眼帘的是一条条评论，然后是发出该条评论的用户。</p>
<p>那么我们可以抽离出 <code>comment</code> 和 <code>user_info</code> 这两个结构体表示前端需要展示的消息，那么它在我们C++后端的请看可能是下面这样的结构体：</p>
<p>完整代码在 <a href="https://github.com/ACking-you/ejson4cpp/blob/master/example/example2.cc" target="_blank" rel="noopener noreffer">example/example2.cc</a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">user_info</span>
<span class="p">{</span>
   <span class="kt">bool</span>        <span class="n">is_follow</span><span class="p">{};</span><span class="c1">//是否关注
</span><span class="c1"></span>   <span class="kt">int64_t</span>     <span class="n">id</span><span class="p">{};</span><span class="c1">//id信息
</span><span class="c1"></span>   <span class="kt">int64_t</span>     <span class="n">follow_count</span><span class="p">{};</span><span class="c1">//关注的博主数量
</span><span class="c1"></span>   <span class="kt">int64_t</span>     <span class="n">follower_count</span><span class="p">{};</span><span class="c1">//粉丝数量
</span><span class="c1"></span>   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span><span class="c1">//用户名
</span><span class="c1"></span><span class="p">};</span>

<span class="k">struct</span> <span class="nc">comment</span>
<span class="p">{</span>
   <span class="kt">int64_t</span>     <span class="n">id</span><span class="p">{};</span><span class="c1">//id信息
</span><span class="c1"></span>   <span class="kt">int64_t</span>     <span class="n">user_id</span><span class="p">{};</span><span class="c1">//用户id信息
</span><span class="c1"></span>   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">created_date</span><span class="p">;</span><span class="c1">//创建时间
</span><span class="c1"></span>   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">content</span><span class="p">;</span><span class="c1">//评论内容
</span><span class="c1"></span><span class="p">};</span>
</code></pre></div><p>那么我们的后端逻辑可能会经历下面的过程：</p>
<ol>
<li>从前端获取json数据（中间一般有鉴权的过程）。</li>
<li>接收json数据并其初始化为对应的C++结构体。</li>
<li>进行该次接口调用的业务逻辑处理。</li>
<li>保存数据到数据库。</li>
</ol>
<p>那么我们用模拟数据来模拟上述过程：</p>
<ol>
<li>
<p>前端的数据：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">comment_json</span>   <span class="o">=</span> <span class="s">&#34;{</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">content</span><span class="s">&#34;: &#34;</span><span class="err">这是一条\</span><span class="s">&#34;测试</span><span class="se">\&#34;</span><span class="s">评论&#34;</span><span class="p">,</span><span class="err">\</span><span class="n">n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">created_date</span><span class="s">&#34;: &#34;</span><span class="mi">2023</span><span class="o">-</span><span class="mo">01</span><span class="o">-</span><span class="mi">16</span><span class="s">&#34;,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">id</span><span class="s">&#34;: 1,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">user_id</span><span class="s">&#34;: 10</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;}&#34;</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">user_info_json</span> <span class="o">=</span> <span class="s">&#34;{</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">follow_count</span><span class="s">&#34;: 12,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">follower_count</span><span class="s">&#34;: 23,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">id</span><span class="s">&#34;: 1,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">is_follow</span><span class="s">&#34;: false,</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;  &#34;</span><span class="n">name</span><span class="s">&#34;: &#34;</span><span class="err">某人名字</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span>
    <span class="s">&#34;}&#34;</span><span class="p">;</span>
</code></pre></div></li>
<li>
<p>将数据转为C++的结构体：
需要先添加下列宏让对应的结构支持json互转</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">user_info</span><span class="p">,</span> <span class="n">is_follow</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">follow_count</span><span class="p">,</span> <span class="n">follower_count</span><span class="p">,</span><span class="n">name</span><span class="p">)</span>
<span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">comment</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">user_id</span><span class="p">,</span> <span class="n">created_date</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
</code></pre></div><p>然后调用对应函数即可转化</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">comment</span>   <span class="n">cmt</span><span class="p">;</span>
<span class="n">user_info</span> <span class="n">uinfo</span><span class="p">;</span>
<span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="n">comment_json</span><span class="p">,</span> <span class="n">cmt</span><span class="p">);</span>
<span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="n">user_info_json</span><span class="p">,</span> <span class="n">uinfo</span><span class="p">);</span>
</code></pre></div></li>
<li>
<p>处理业务逻辑，这个跳过。</p>
</li>
<li>
<p>保存数据到数据库，这个模拟为保存数据到文件：
我们可以创建一个 <code>dict_t</code> 类型的 <code>JObject</code> ，然后把刚才的结构体以 <code>key-value</code> 对的形式放进去，最后再调用 <code>ToFile</code> 函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="c1">// 4.save data to database(we simulate it to local file)
</span><span class="c1"></span><span class="k">auto</span> <span class="n">object</span> <span class="o">=</span> <span class="n">JObject</span><span class="o">::</span><span class="n">Dict</span><span class="p">();</span>
<span class="n">object</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;comment&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">cmt</span><span class="p">);</span>
<span class="n">object</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;user_info&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">uinfo</span><span class="p">);</span>
<span class="n">ejson</span><span class="o">::</span><span class="n">Parser</span><span class="o">::</span><span class="n">ToFile</span><span class="p">(</span><span class="n">DATA_PATH</span><span class="p">,</span> <span class="n">object</span><span class="p">);</span>
</code></pre></div><p>最终得到下列json数据到文件中：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="p">{</span>
  <span class="nt">&#34;comment&#34;</span><span class="p">:</span> <span class="p">{</span>
    <span class="nt">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;这是一条&#34;</span><span class="err">测试</span><span class="s2">&#34;评论&#34;</span><span class="p">,</span>
    <span class="nt">&#34;created_date&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-01-16&#34;</span><span class="p">,</span>
    <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="nt">&#34;user_id&#34;</span><span class="p">:</span> <span class="mi">10</span>
  <span class="p">},</span>
  <span class="nt">&#34;user_info&#34;</span><span class="p">:</span> <span class="p">{</span>
    <span class="nt">&#34;follow_count&#34;</span><span class="p">:</span> <span class="mi">12</span><span class="p">,</span>
    <span class="nt">&#34;follower_count&#34;</span><span class="p">:</span> <span class="mi">23</span><span class="p">,</span>
    <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="nt">&#34;is_follow&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;某人名字&#34;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></li>
</ol>
<h2 id="api介绍">API介绍</h2>
<p>对所有类成员的描述的信息，可以点开 <code>doc/html/index.html</code> 进行查看。如果需要其他语言版本的文档，可以自己通过 <code>Doxygen</code> 进行生成。</p>
<h3 id="通过命名风格识别api">通过命名风格识别API</h3>
<ol>
<li>
<p>所有对外暴露的静态成员函数均以 <code>PascalCase</code> 风格命名。如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">namespace</span> <span class="n">ejson</span> <span class="p">{</span>
<span class="k">class</span> <span class="nc">Parser</span>
<span class="p">{</span>
   <span class="k">static</span> <span class="n">JObject</span> <span class="nf">FromJSON</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span> <span class="o">&amp;</span><span class="n">content</span><span class="p">,</span><span class="kt">bool</span> <span class="n">skip_comment</span><span class="o">=</span><span class="nb">false</span><span class="p">);</span>

   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">static</span> <span class="kt">void</span> <span class="n">FromJSON</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span> <span class="n">T</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">,</span><span class="kt">bool</span> <span class="n">skip_comment</span><span class="o">=</span><span class="nb">false</span><span class="p">);</span>

   <span class="k">static</span> <span class="n">JObject</span> <span class="nf">FromFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span><span class="kt">bool</span> <span class="n">skip_comment</span><span class="o">=</span><span class="nb">false</span><span class="p">);</span>

   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">static</span> <span class="kt">void</span> <span class="n">FromFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">T</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">);</span>

   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">ToJSON</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">src</span><span class="p">,</span><span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
                        <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>

   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">static</span> <span class="kt">void</span> <span class="n">ToFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span> 
                      <span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
                      <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>

   <span class="k">static</span> <span class="kt">void</span> <span class="nf">ToFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">JObject</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span>
                     <span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
                      <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">JObject</span>
<span class="p">{</span>
   <span class="k">static</span> <span class="k">auto</span> <span class="nf">Dict</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">JObject</span><span class="p">;</span>
   <span class="k">static</span> <span class="k">auto</span> <span class="nf">List</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">JObject</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>   <span class="c1">// namespace ejson
</span></code></pre></div></li>
<li>
<p>所有想要暴露的普通成员函数均以 <code>snack_case</code> 风格命名，如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">namespace</span> <span class="n">ejson</span> <span class="p">{</span>
<span class="k">class</span> <span class="nc">JObject</span>
<span class="p">{</span>
   <span class="k">auto</span> <span class="nf">type</span><span class="p">()</span> <span class="k">const</span> <span class="o">-&gt;</span> <span class="n">Type</span><span class="p">;</span>

   <span class="k">auto</span> <span class="nf">at</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span> <span class="o">&amp;</span><span class="n">key</span><span class="p">)</span> <span class="k">const</span> <span class="o">-&gt;</span> <span class="n">ObjectRef</span><span class="p">;</span>

   <span class="k">auto</span> <span class="nf">to_string</span><span class="p">(</span><span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
                                  <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span> <span class="k">const</span> <span class="o">-&gt;</span> <span class="n">string</span><span class="p">;</span>

   <span class="kt">void</span> <span class="nf">push_back</span><span class="p">(</span><span class="n">JObject</span> <span class="n">item</span><span class="p">);</span>

   <span class="kt">void</span> <span class="nf">pop_back</span><span class="p">();</span>

   <span class="k">auto</span> <span class="nf">has_key</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span> <span class="o">&amp;</span><span class="n">key</span><span class="p">)</span> <span class="k">const</span> <span class="o">-&gt;</span> <span class="kt">bool</span><span class="p">;</span>

   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">auto</span> <span class="n">cast</span><span class="p">()</span> <span class="k">const</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">ObjectRef</span>
<span class="p">{</span>
   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="k">auto</span> <span class="n">get_from</span><span class="p">(</span><span class="n">T</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ObjectRef</span> <span class="o">&amp;</span><span class="p">;</span>
   <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
   <span class="kt">void</span> <span class="n">get_to</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>   <span class="c1">// namespace ejson
</span></code></pre></div></li>
<li>
<p>其余还有两个函数，如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">namespace</span> <span class="n">ejson_literals</span> <span class="p">{</span>

<span class="k">auto</span> <span class="k">operator</span><span class="s">&#34;&#34;</span><span class="n">_json</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">json</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">JObject</span><span class="p">;</span>

<span class="k">auto</span> <span class="nf">float_d</span><span class="p">(</span><span class="kt">int</span> <span class="n">d</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">int</span><span class="p">;</span>

<span class="p">}</span>   <span class="c1">// namespace ejson_literals
</span></code></pre></div></li>
</ol>
<h3 id="宏定义">宏定义</h3>
<p>利用宏定义可以方便且迅速的让自定义类型支持 <code>FromJSON</code> 和 <code>ToJSON</code> 系列函数。</p>
<p>实际上自定义类型在使用 <code>FromJSON</code> 时，只需要定义对应的 <code>from_json</code> 函数，使用 <code>ToJSON</code> 时，只需定义对应的 <code>to_json</code> 函数。</p>
<p>下列是 from_json 和 to_json 的函数签名：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">from_json</span><span class="p">(</span><span class="k">const</span> <span class="n">ejson</span><span class="o">::</span><span class="n">JObject</span><span class="o">&amp;</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">ejson_t</span><span class="p">);</span>

<span class="kt">void</span> <span class="nf">to_json</span><span class="p">(</span><span class="n">ejson</span><span class="o">::</span><span class="n">JObject</span><span class="o">&amp;</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">ejson_t</span><span class="p">);</span>
</code></pre></div><p>你可以像下面这样自己实现上面这两个函数来让自定义类型支持 <code>FromJSON</code> 和 <code>ToJSON</code>  函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">void</span> <span class="nf">to_json</span><span class="p">(</span><span class="n">ejson</span><span class="o">::</span><span class="n">JObject</span><span class="o">&amp;</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="k">const</span> <span class="n">student</span><span class="o">&amp;</span> <span class="n">ejson_t</span><span class="p">)</span>
<span class="p">{</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">from_json</span><span class="p">(</span><span class="k">const</span> <span class="n">ejson</span><span class="o">::</span><span class="n">JObject</span><span class="o">&amp;</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="n">student</span><span class="o">&amp;</span> <span class="n">ejson_t</span><span class="p">)</span>
<span class="p">{</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div><p>如果属性是 <code>private</code> 的，那么可以像下面这样侵入式的定义：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="k">friend</span> <span class="kt">void</span> <span class="nf">to_json</span><span class="p">(</span><span class="n">ejson</span><span class="o">::</span><span class="n">JObject</span><span class="o">&amp;</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="k">const</span> <span class="n">student</span><span class="o">&amp;</span> <span class="n">ejson_t</span><span class="p">)</span>
   <span class="p">{</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
   <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div><h4 id="from_json_funcfrom_json_friend_func">FROM_JSON_FUNC&amp;FROM_JSON_FRIEND_FUNC</h4>
<p>用于简化 <code>from_json</code> 函数定义的书写，例如前面对于 <code>strudent</code> 类型的 <code>from_json</code> 函数可以这样写：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//非侵入式
</span><span class="c1"></span><span class="n">FROM_JSON_FUNC</span><span class="p">(</span><span class="n">student</span><span class="p">,</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="n">ejson_t</span><span class="p">)</span> <span class="p">{</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
    <span class="c1">//侵入式
</span><span class="c1"></span>   <span class="n">FROM_JSON_FRIEND_FUNC</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">ejson_j</span><span class="p">,</span><span class="n">ejson_t</span><span class="p">)</span>
   <span class="p">{</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_to</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
   <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div><h4 id="to_json_functo_json_friend_func">TO_JSON_FUNC&amp;TO_JSON_FRIEND_FUNC</h4>
<p>用于简化 <code>to_json</code> 函数定义的书写，例如前面对于 <code>strudent</code> 类型的 <code>to_json</code> 函数可以这样写：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//非侵入式
</span><span class="c1"></span><span class="n">TO_JSON_FUNC</span><span class="p">(</span><span class="n">student</span><span class="p">,</span> <span class="n">ejson_j</span><span class="p">,</span> <span class="n">ejson_t</span><span class="p">)</span> <span class="p">{</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
   <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
    <span class="c1">//侵入式
</span><span class="c1"></span>   <span class="n">TO_JSON_FRIEND_FUNC</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">ejson_j</span><span class="p">,</span><span class="n">ejson_t</span><span class="p">)</span>
   <span class="p">{</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;id&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;score&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">score</span><span class="p">);</span>
      <span class="n">ejson_j</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="n">ejson_t</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
   <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div><h4 id="auto_gen_non_intrusiveauto_gen_intrusive">AUTO_GEN_NON_INTRUSIVE&amp;AUTO_GEN_INTRUSIVE</h4>
<p>这两个宏可以帮助你一键生成之前例子中的 <code>to_json</code> 和 <code>from_json</code> 函数。</p>
<p>前面的代码可以替换为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//非侵入式
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">id</span><span class="p">,</span><span class="n">score</span><span class="p">,</span><span class="n">name</span><span class="p">)</span>
    
<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
<span class="c1">//侵入式
</span><span class="c1"></span><span class="n">AUTO_GEN_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">id</span><span class="p">,</span><span class="n">score</span><span class="p">,</span><span class="n">name</span><span class="p">)</span>
    
<span class="k">private</span><span class="o">:</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div><h4 id="enable_json_cout">ENABLE_JSON_COUT</h4>
<p>自动生成对应类型的 <code>operator&lt;&lt;(ostream&amp;,T)</code> 运算符重载，用于将对应类型支持 <code>cout</code> 打印出json格式。该宏可以为多个类型生成。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="kt">int</span>         <span class="n">score</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">info</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">;</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">msg</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//让对应类型支持json格式化
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">id</span><span class="p">,</span><span class="n">score</span><span class="p">,</span><span class="n">name</span><span class="p">)</span>
<span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">info</span><span class="p">,</span><span class="n">id</span><span class="p">,</span><span class="n">msg</span><span class="p">)</span>
    
<span class="c1">//支持json格式cout打印
</span><span class="c1"></span><span class="n">ENABLE_JSON_COUT</span><span class="p">(</span><span class="n">student</span><span class="p">,</span><span class="n">info</span><span class="p">)</span>
</code></pre></div><h3 id="fromjson系列函数">FromJSON系列函数</h3>
<h4 id="参数说明">参数说明</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="n">JObject</span> <span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span> <span class="o">&amp;</span><span class="n">content</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">skip_comment</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>
</code></pre></div><p>根据json字符串内容反序列化为JObject结构。</p>
<p>参数说明：</p>
<ul>
<li><code>content</code>：需要解析的json资源，这是一个string_view类型的参数，支持C风格字符串和 <code>std::string</code>。</li>
<li><code>skip_comment</code>：是否需要支持跳过注释，默认为false，未开启。</li>
</ul>
<p>返回值：</p>
<ul>
<li>返回解析完的 JObject 类型。</li>
</ul>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
<span class="k">static</span> <span class="kt">void</span> <span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span> <span class="n">T</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">,</span><span class="kt">bool</span> <span class="n">skip_comment</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span>
</code></pre></div><p>根据json字符串内容反序列化数据到 <code>dst</code>。</p>
<p>参数说明：</p>
<ul>
<li><code>src</code>：需要解析的json资源，这是一个string_view类型的参数，支持C风格字符串和 <code>std::string</code>。</li>
<li><code>dst</code>：需要初始化的变量，可以是自定义类型。</li>
<li><code>skip_comment</code>：是否需要支持跳过注释，默认为false，未开启。</li>
</ul>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="n">JObject</span><span class="o">&amp;</span> <span class="n">Parser</span><span class="o">::</span><span class="n">FromFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">skip_comment</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>
</code></pre></div><p>根据文件中的 json 数据获取 JObject&amp;，这个JObject是thread_local变量，也就是每个线程共用一个JObject。所以请注意，当您调用此函数时，将更新这个共用的 JObject  的值。</p>
<p>参数说明：</p>
<ul>
<li><code>filename</code> ：json文件路径。</li>
<li><code>skip_comment</code> ：是否需要支持跳过注释，默认为false，未开启。</li>
</ul>
<p>返回值：</p>
<ul>
<li>同一个线程共用的JObject&amp;。</li>
</ul>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="kt">void</span> <span class="n">Parser</span><span class="o">::</span><span class="n">FromFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">T</span> <span class="o">&amp;</span><span class="n">dst</span><span class="p">,</span><span class="kt">bool</span> <span class="n">skip_comment</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>
</code></pre></div><p>根据文件中的json数据设置 <code>dst</code> 的值。</p>
<p>参数说明：</p>
<ul>
<li><code>filename</code> ：json文件路径。</li>
<li><code>dst</code> ：需要初始化的变量。</li>
<li><code>skip_comment</code> ：是否需要支持跳过注释，默认为false，未开启。</li>
</ul>
<h4 id="使用示例">使用示例</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;ejson/parser.h&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">ejson</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">Score</span>
<span class="p">{</span>
   <span class="kt">double</span> <span class="n">p</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">{};</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
   <span class="n">Score</span>       <span class="n">score</span><span class="p">{};</span>
<span class="p">};</span>
<span class="c1">//为Score类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="c1">//为student类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span>
<span class="c1">//重载方便cout打印数据
</span><span class="c1"></span><span class="n">ENABLE_JSON_COUT</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span><span class="n">student</span><span class="p">)</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
   <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">json1</span> <span class="o">=</span>
     <span class="n">R</span><span class="s">&#34;({&#34;</span><span class="n">id</span><span class="s">&#34;:324,&#34;</span><span class="n">name</span><span class="s">&#34;:&#34;</span><span class="err">刘</span><span class="n">xx</span><span class="s">&#34;,&#34;</span><span class="n">score</span><span class="s">&#34;:{&#34;</span><span class="n">p</span><span class="s">&#34;:2342343243242.124}})&#34;</span><span class="p">;</span>
    <span class="n">student</span> <span class="n">stu</span><span class="p">;</span>
    <span class="c1">//使用FromJSON初始化stu变量
</span><span class="c1"></span>       <span class="n">Parser</span><span class="o">::</span><span class="n">FromJSON</span><span class="p">(</span><span class="n">json1</span><span class="p">,</span><span class="n">stu</span><span class="p">);</span>
    <span class="c1">//使用FromFile初始化stu变量
</span><span class="c1"></span>    <span class="n">Parser</span><span class="o">::</span><span class="n">FromFile</span><span class="p">(</span><span class="s">&#34;json文件路径&#34;</span><span class="p">,</span><span class="n">stu</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">stu</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><h3 id="tojson系列函数">ToJSON系列函数</h3>
<h4 id="参数说明-1">参数说明</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
<span class="k">static</span> <span class="k">auto</span> <span class="n">Parser</span><span class="o">::</span><span class="n">ToJSON</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">src</span><span class="p">,</span><span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
                        <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">;</span>
</code></pre></div><p>将任意类型序列化为json字符串返回。</p>
<p>参数说明：</p>
<ul>
<li><code>src</code> ：需要序列化为json字符串的数据。</li>
<li><code>indent</code> ：是否需要美化json输出，小于0表示美化，其余情况为美化时的缩进长度，默认不美化。</li>
<li><code>indent_char</code> ：美化时填入缩进的字符，默认为 <code>' '</code> 。</li>
<li><code>is_esc</code> ：是否需要识别转义字符，默认不识别。</li>
</ul>
<p>返回值：</p>
<ul>
<li>json字符串。</li>
</ul>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span>
<span class="k">static</span> <span class="kt">void</span> <span class="n">ToFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">,</span>
                   <span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
                      <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">);</span>
</code></pre></div><p>根据 <code>src</code> 中的数据序列化为json数据到文件中。</p>
<p>参数说明：</p>
<ul>
<li><code>filename</code> ：需要写入的文件路径。</li>
<li><code>src</code> ：需要序列化的变量。</li>
<li><code>indent</code> ：是否需要美化json输出，小于0表示美化，其余情况为美化时的缩进长度，默认不美化。</li>
<li><code>indent_char</code> ：美化时填入缩进的字符，默认为 <code>' '</code> 。</li>
<li><code>is_esc</code> ：是否需要识别转义字符，默认不识别。</li>
</ul>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="kt">void</span> <span class="n">ToFile</span><span class="p">(</span><span class="n">string_view</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">filename</span><span class="p">,</span> <span class="n">JObject</span> <span class="k">const</span> <span class="o">&amp;</span><span class="n">src</span>
                   <span class="k">const</span> <span class="kt">int</span> <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
                      <span class="kt">bool</span> <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span><span class="p">)</span>
</code></pre></div><p>将JObject中的数据转为json写入到文件中。</p>
<p>参数说明：</p>
<ul>
<li><code>filename</code> ：需要写入的文件路径。</li>
<li><code>src</code> ：JObject变量。</li>
<li><code>indent</code> ：是否需要美化json输出，小于0表示美化，其余情况为美化时的缩进长度，默认不美化。</li>
<li><code>indent_char</code> ：美化时填入缩进的字符，默认为 <code>' '</code> 。</li>
<li><code>is_esc</code> ：是否需要识别转义字符，默认不识别。</li>
</ul>
<h4 id="使用示例-1">使用示例</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;ejson/parser.h&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">ejson</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">Score</span>
<span class="p">{</span>
   <span class="kt">double</span> <span class="n">p</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">{};</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
   <span class="n">Score</span>       <span class="n">score</span><span class="p">{};</span>
<span class="p">};</span>
<span class="c1">//为Score类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="c1">//为student类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span>
<span class="c1">//重载方便cout打印数据
</span><span class="c1"></span><span class="n">ENABLE_JSON_COUT</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span><span class="n">student</span><span class="p">)</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
    <span class="n">student</span> <span class="n">stu</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="mi">324</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;刘xx&#34;</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">score</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="mf">2342343243242.124</span><span class="p">;</span>
    <span class="c1">//使用ToJSON进行序列化
</span><span class="c1"></span>       <span class="k">auto</span> <span class="n">json_data</span> <span class="o">=</span> <span class="n">Parser</span><span class="o">::</span><span class="n">ToJSON</span><span class="p">(</span><span class="n">stu</span><span class="p">);</span>
    <span class="c1">//使用ToFile将数据序列化到文件
</span><span class="c1"></span>    <span class="n">Parser</span><span class="o">::</span><span class="n">ToFile</span><span class="p">(</span><span class="s">&#34;文件路径&#34;</span><span class="p">,</span><span class="n">stu</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">stu</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><h3 id="jobject系列函数">JObject系列函数</h3>
<h4 id="jobject的构造函数">JObject的构造函数</h4>
<p>只需要清楚以下几点：</p>
<ol>
<li>JObject有无参构造，但是无参构造产生的JObject为null类型，无法进行正常使用。</li>
<li>JObject的构造函数可以直接接受大部分类型，且包括自定义类型和部分stl容器。</li>
<li>JObject本身不支持拷贝构造，只支持移动构造。</li>
</ol>
<p>前面的 ToJSON API完全可以用下列方式替代，因为所有的序列化过程其实都是构造JObject来进行：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;ejson/parser.h&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">ejson</span><span class="p">;</span>

<span class="k">struct</span> <span class="nc">Score</span>
<span class="p">{</span>
   <span class="kt">double</span> <span class="n">p</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">student</span>
<span class="p">{</span>
   <span class="kt">int</span>         <span class="n">id</span><span class="p">{};</span>
   <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
   <span class="n">Score</span>       <span class="n">score</span><span class="p">{};</span>
<span class="p">};</span>
<span class="c1">//为Score类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="c1">//为student类型自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">student</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span>
<span class="c1">//重载方便cout打印数据
</span><span class="c1"></span><span class="n">ENABLE_JSON_COUT</span><span class="p">(</span><span class="n">Score</span><span class="p">,</span><span class="n">student</span><span class="p">)</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
    <span class="n">student</span> <span class="n">stu</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="mi">324</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&#34;刘xx&#34;</span><span class="p">;</span>
    <span class="n">stu</span><span class="p">.</span><span class="n">score</span><span class="p">.</span><span class="n">p</span> <span class="o">=</span> <span class="mf">2342343243242.124</span><span class="p">;</span>
    <span class="c1">//构造JObject并使用其成员函数
</span><span class="c1"></span>       <span class="k">auto</span> <span class="n">json_data</span> <span class="o">=</span> <span class="n">JObject</span><span class="p">(</span><span class="n">stu</span><span class="p">).</span><span class="n">to_string</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">stu</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><h4 id="jobject的成员函数">JObject的成员函数</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">Type</span> <span class="n">JObject</span><span class="o">::</span><span class="n">type</span><span class="p">()</span> <span class="k">const</span>
</code></pre></div><p>返回当前JObject对象的类型，具体的类型有下列情况：</p>
<ul>
<li><code>kNull</code> ：值为null类型</li>
<li><code>kBool</code>：值为bool类型</li>
<li><code>kInt</code>：值为整数类型</li>
<li><code>kDouble</code>：值为浮点类型</li>
<li><code>kStr</code>：值为字符串类型</li>
<li><code>kList</code>：值为列表类型</li>
<li><code>kDict</code>：值为字典类型（或叫做对象类型）</li>
</ul>
<hr>
<h5 id="kdict">kDict</h5>
<p>当你的JObject的类型为 <code>kDict</code> 时，下列成员函数可供使用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="kt">bool</span> <span class="n">JObject</span><span class="o">::</span><span class="n">has_key</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">)</span>    <span class="k">const</span>
</code></pre></div><ul>
<li>判断 <code>JObject</code> 中是否存在包含 <code>key</code> 的映射。</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">ObjectRef</span> <span class="n">JObject</span><span class="o">::</span><span class="n">at</span><span class="p">(</span><span class="k">const</span> <span class="n">str_t</span><span class="o">&amp;</span> <span class="n">key</span><span class="p">)</span>    <span class="k">const</span>
</code></pre></div><ul>
<li>
<p>根据key取出对应映射的value，value以 ObjectRef 类型的方式提供。</p>
<p>而ObjectRef类型有这两个关键的成员函数：</p>
<ul>
<li>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">ObjectRef</span><span class="o">&amp;</span> <span class="n">JObject</span><span class="o">::</span><span class="n">ObjectRef</span><span class="o">::</span><span class="n">get_from</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span> <span class="n">src</span><span class="p">)</span>   
</code></pre></div></li>
</ul>
<pre><code>
  从 `src` 中获取数据填充到 `JObject` 中，若 `src` 为自定义类型需要自定义 `to_json` 方法。

* ```cpp
ObjectRef&amp; JObject::ObjectRef::get_from(T&amp; dst)
</code></pre><pre><code>从 `JObject` 中获取数据填充到 `dst` 中，若 `dst` 为自定义类型需要自定义 `from_json` 方法。
</code></pre>
</li>
</ul>
<hr>
<h5 id="klist">kList</h5>
<p>当JObject类型为 <code>kList</code> 时，下列成员函数可用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="n">JObject</span><span class="o">::</span><span class="n">push_back</span><span class="p">(</span><span class="n">JObject</span> <span class="n">item</span><span class="p">);</span>
</code></pre></div><ul>
<li>插入一个值到 <code>JObject</code> 列表的尾部，可以插入任意类型，但都需要显式的转化为 <code>JObject</code> 类型，如 <code>JObject(324234)</code>。</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="n">JObject</span><span class="o">::</span><span class="n">pop_back</span><span class="p">()</span>
</code></pre></div><ul>
<li>删除列表中末尾的值。</li>
</ul>
<hr>
<h5 id="to_string">to_string</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">string</span> <span class="n">JObject</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span>
<span class="kt">int</span>    <span class="n">indent</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="kt">char</span>   <span class="n">indent_char</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">,</span>
<span class="kt">bool</span>   <span class="n">is_esc</span> <span class="o">=</span> <span class="nb">false</span> 
<span class="p">)</span><span class="k">const</span>
</code></pre></div><p>序列化最终调用的API，将JObject序列化为json字符串返回。</p>
<p>参数说明：</p>
<ul>
<li><code>indent</code> ：用于判断json解析是否需要美化，如果需要美化，则该值为缩进的长度。该值小于0时不进行美化，默认值为-1。</li>
<li><code>indent_char</code>：缩进填入的字符，默认为 <code>' '</code> 。</li>
<li><code>is_esc</code>：是否需要对转义字符进行处理，默认不开启。</li>
</ul>
<p>返回值：</p>
<ul>
<li>序列化后端json字符串。</li>
</ul>
<hr>
<h5 id="static">static</h5>
<p>为了方便快速创建 <code>dict_t</code> 类型和 <code>list_t</code> 类型的 <code>JObject</code> ，定义了下列静态函数：</p>
<hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="n">JObject</span> <span class="n">JObject</span><span class="o">::</span><span class="n">Dict</span><span class="p">()</span>
</code></pre></div><p>使用如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;ejson/parser.h&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">ejson</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="c1">//构造JObject并使用其成员函数
</span><span class="c1"></span>       <span class="k">auto</span> <span class="n">json</span> <span class="o">=</span> <span class="n">JObject</span><span class="o">::</span><span class="n">Dict</span><span class="p">();</span>
    <span class="n">json</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;a&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="s">&#34;bc&#34;</span><span class="p">);</span>
    <span class="n">json</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="s">&#34;d&#34;</span><span class="p">).</span><span class="n">get_from</span><span class="p">(</span><span class="s">&#34;ef&#34;</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">json</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div><hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="k">static</span> <span class="n">JObject</span> <span class="n">JObject</span><span class="o">::</span><span class="n">List</span><span class="p">()</span>
</code></pre></div><p>使用如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;ejson/parser.h&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">ejson</span><span class="p">;</span>
<span class="k">struct</span> <span class="nc">custom_type</span><span class="p">{</span>
    <span class="kt">int</span> <span class="n">id</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">data</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">//自动生成to_json和from_json函数
</span><span class="c1"></span><span class="n">AUTO_GEN_NON_INTRUSIVE</span><span class="p">(</span><span class="n">custom_type</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span><span class="n">data</span><span class="p">)</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
    <span class="c1">//构造JObject并使用其成员函数
</span><span class="c1"></span>       <span class="k">auto</span> <span class="n">json</span> <span class="o">=</span> <span class="n">JObject</span><span class="o">::</span><span class="n">List</span><span class="p">();</span>
    <span class="n">json</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">JObject</span><span class="p">(</span><span class="s">&#34;abc&#34;</span><span class="p">));</span>
    <span class="n">custom_type</span> <span class="n">v</span><span class="p">{</span><span class="mi">1</span><span class="p">,{</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">}};</span>
       <span class="n">json</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">JObject</span><span class="p">(</span><span class="n">v</span><span class="p">));</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">json</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div><h2 id="注意事项">注意事项</h2>
<p>在使用本库时需要注意几点：</p>
<ol>
<li>本库不对你使用的字符编码进行验证，加入你使用 gbk 编码的json数据进行解析得到还是gbk编码的，所以这点需要注意，建议都使用utrf8编码。</li>
<li>本库只支持对 `` 和 <code>&quot;</code> 的转义，其他的诸如 <code>\u</code> <code>\b</code> 等功能暂时不支持，我还是建议在json数据中不要存储二进制文件，如果需要存储二进制文件，后续的版本中可能会增base64编码的支持。</li>
<li>本库对所有字符串解析到 <code>JObject</code> 中的过程都是浅拷贝（只拷贝了指针），故如果需要使用原生 <code>JObject</code> 进行数据的存储需要额外的注意内存的所有权和生命周期，建议使用 <code>JObject</code> 进行短期的解析而不是长期的存储，在大多数情况下直接使用函数是最好的选择，后续可能会出一个深拷贝的 <code>JObject</code> 那样的结构才适合存储。</li>
<li>本库所有的错误均以异常抛出，好处在于可以模拟递归调用栈的栈信息进行打印，坏处当然是要写 <code>try catch</code>。</li>
</ol>
</div><div class="post-footer" id="post-footer">
    <div class="post-info"><div class="post-info-tag"><span><a href="/tags/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/">ejson4cpp使用文档</a>
                </span></div><div class="post-info-line"><div class="post-info-mod">
                <span>更新于 2023-01-17</span>
            </div><div class="post-info-mod"></div>
        </div><div class="post-info-share">
            <span><a href="javascript:void(0);" title="分享到 Twitter" data-sharer="twitter" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档" data-hashtags="ejson4cpp使用文档"><i class="fab fa-twitter fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Facebook" data-sharer="facebook" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-hashtag="ejson4cpp使用文档"><i class="fab fa-facebook-square fa-fw"></i></a><a href="javascript:void(0);" title="分享到 WhatsApp" data-sharer="whatsapp" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档" data-web><i class="fab fa-whatsapp fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Line" data-sharer="line" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档"><i class="fab fa-line fa-fw"></i></a><a href="javascript:void(0);" title="分享到 微博" data-sharer="weibo" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档" data-image="https://img-blog.csdnimg.cn/2fe50a8ccac142f6b744b88999d0dc6c.png"><i class="fab fa-weibo fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Myspace" data-sharer="myspace" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档" data-description="ejson4cpp使用文档"><i data-svg-src="/lib/simple-icons/icons/myspace.min.svg"></i></a><a href="javascript:void(0);" title="分享到 Blogger" data-sharer="blogger" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档" data-description="ejson4cpp使用文档"><i class="fab fa-blogger fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Evernote" data-sharer="evernote" data-url="https://acking-you.github.io/posts/ejson4cpp%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/" data-title="ejson4cpp使用文档"><i class="fab fa-evernote fa-fw"></i></a></span>
        </div></div><div class="post-nav"><a href="/posts/clion%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%AE%8C%E5%85%A8%E8%A7%A3%E6%9E%90/" class="prev" rel="prev" title="CLion开发环境配置完全解析"><i class="fas fa-angle-left fa-fw"></i>Previous Post</a>
            <a href="/posts/c&#43;&#43;%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5%E5%BF%85%E5%A4%87%E6%B5%8B%E8%AF%95%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E8%A6%86%E7%9B%96%E6%B5%8B%E8%AF%95%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E6%A3%80%E6%B5%8B/" class="next" rel="next" title="C&#43;&#43;工程实践必备：测试、基准测试、覆盖测试、性能分析、内存泄漏检测">Next Post<i class="fas fa-angle-right fa-fw"></i></a></div></div>
</div></article></div>
            </main>
            <footer class="footer"><div class="footer-container"><div class="footer-line">由 <a href="https://gohugo.io/" target="_blank" rel="noopener noreffer" title="Hugo 0.86.0">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/khusika/FeelIt" target="_blank" rel="noopener noreffer" title="FeelIt 1.0.1"><i class="fas fa-hand-holding-heart fa-fw"></i> FeelIt</a>
        </div><div class="footer-line" itemscope itemtype="http://schema.org/CreativeWork"><i class="far fa-copyright fa-fw"></i><span itemprop="copyrightYear">2023</span><span class="author" itemprop="copyrightHolder">&nbsp;<a href="/"></a></span></div>
</div>
</footer>
        </div>

        <div id="fixed-buttons"><a href="#" id="back-to-top" class="fixed-button" title="回到顶部">
                <i class="fas fa-chevron-up fa-fw"></i>
            </a></div><link rel="stylesheet" href="/lib/fontawesome-free/all.min.css"><link rel="stylesheet" href="/lib/animate/animate.min.css"><link rel="stylesheet" href="/lib/katex/katex.min.css"><link rel="stylesheet" href="/lib/katex/copy-tex.min.css"><script src="/lib/autocomplete/autocomplete.min.js"></script><script src="/lib/lunr/lunr.min.js"></script><script src="/lib/lunr/lunr.stemmer.support.min.js"></script><script src="/lib/lunr/lunr.zh.min.js"></script><script src="/lib/lazysizes/lazysizes.min.js"></script><script src="/lib/clipboard/clipboard.min.js"></script><script src="/lib/sharer/sharer.min.js"></script><script src="/lib/katex/katex.min.js"></script><script src="/lib/katex/auto-render.min.js"></script><script src="/lib/katex/copy-tex.min.js"></script><script src="/lib/katex/mhchem.min.js"></script><script>window.config={"code":{"copyTitle":"复制到剪贴板","maxShownLines":200},"comment":{},"math":{"delimiters":[{"display":true,"left":"$$","right":"$$"},{"display":true,"left":"\\[","right":"\\]"},{"display":false,"left":"$","right":"$"},{"display":false,"left":"\\(","right":"\\)"}],"strict":false},"search":{"highlightTag":"em","lunrIndexURL":"/index.json","lunrLanguageCode":"zh","lunrSegmentitURL":"/lib/lunr/lunr.segmentit.js","maxResultLength":100,"noResultsFound":"没有找到结果","snippetLength":50,"type":"lunr"}};</script><script src="/js/theme.min.js"></script></body></html>
